﻿using Newtonsoft.Json;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using Xmeta.Test.Common;
using Xmeta.Test.Model;

namespace Xmeta.Test
{
    internal class Program
    {
        static void Main(string[] args)
        {



            //对称密钥
            var Asekey = "NQXjZ34lNtOhOAvOy5DvOQ==";

            //xmeta公钥
            var XmetaPubkey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0c5YFZZe+JTDnWGlxYF93H4Eo84xMqoUN2Culy8MWmIy8GPHuPm/OC66vEMH7uPt+zzCyJMTwgFecyvKLwdJ6rTRkfKEjqaTPRZNbDb7R+kZ9C4XLNx6bbzSx3Lga4j3xUf96YMXH3CHpUcw0+xHhzo21a6FBA09jQpI4ROY+kWtpE051TX6Ky/XVZ0t2fqu7h12sciGyDeTp9ojHxiokbAg+W7OEvL1xb1SCEZrkGLVy4NDPb/P9yuXtmZlqwfBoErXwVTj9jwO0A9bDSCvQM0+sJRGVpcVyXgZsmILyITr0FT+uIAEW/kbWTBKHEC2vXHkGleX0RoS9T8MGp422wIDAQAB";

            //一级平台私钥
            var privateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCoG1EzpvaS9TieqKSS3K7W23+Wt6KJpCkZNR85w+y8Qb4VFNQU/gVaG205dHSjo/Nb7zDEgjyGbuYe9XA+Dx/8mI+Leb5Gb+SN0Bx5ePZS1ooaccrJd0xQF6tuj42f8o6HB0GBo6O/GzuYcfnGi2UFnsQZV+sn3Xl6YPNseppz/EhO1X1/VLuv98ueIPxKz7g6bN8yKc2MvJ3pQYvr1Yy7EZAZ1ocTXzWDqdd48ZcCr/2w34ES1O27LJ3wrpQV39unmmLg1W21qRHpVJkuPTdCy9CoDa0KqjtpX3Ml+HqDeq2kIpDFbfefmkwIUCKI2lSMNln5vvhcLCOm+tFHJda/AgMBAAECggEBAKJq2jaUbxEnec/Y0kDOlOIj6o7c114yzD59k7DE+jodLqDBofKyRst7SjlDqdnc8qh1XeHOjtm31gA9VHexN09euvmf41W8j87wLkKyuxLoE0BfhvTFnWaYp9pHOic6O7h8Ky8swm1Gy3qLTC8myLD4ZzCxQBMhKVgyyZ2aixXZLcn76CfCtZITgydPt0Y5+tE6xL1tj1JE5Xd9LTJt0iOpVpk9BLfKFE9y9Koki9975GJkcJFS2c2gdctN16rxValfAfYJxZI2f9WBQrsIa5SxQdfjjJRiRyNRoBQmh9hqWIyzunjTbuL+gPPsJK4INSJMsXpXix0IzjFzjx1d4dECgYEA0AY3EdJdNCvC82IT9SGMmCcNT5K6lty8RwSplzIf4FXoBthlH0nkuinMq3gOc0/r5qkyfwyyfMx6hDQ5VLinHA0cOg5M6Lzzef4DfUo1WX/n0wdDj55dHmQQRr2XUOXeyDaWFSth4aAUo/xOvak3nqIfZ7myRqLoPKa0784FIUcCgYEAzuBc2bAFGr93+2z89nKTyp0MQj4dGdRBE8wmoqp0jNl9ee4lbNRWvLI8NvnPpeIowfWrPcO7/Igr9qr/ZtQ1LyGi2kIcDgrG/pFDIJJFrGheNo6otajB0CLhgUN35X/DOxt/oy9JoDs3ONiPyWope+g7BN4/tAOFCdztBFUWmskCgYALo71jFuU2LRisa5l4RtdKEC1TfX9JP7KdOqqOljRoZgYkk+kclhLhQ8N6+K2+UAOAFYmIyFoYV4ynZxCqJ+bZz/X7XZ96ClCJS+hAE23mwxxil251U8QcFjc+7g7QbPxJMZy2NIY2jLF693wkapp9Gs8tC5vpDeZ2tlE7dcidswKBgEPB1odyEGnvVkPiMYQiiOduwqobn/pqu5nZXroebCgJwAAkkNtxPKt3ESPMdEdXqJPGe/yx1CtlCkkzPo2WaYjzUlx8FKZAv2Z3e236mplaYakq1nURPdGG6yckSuu/CdmdKxPulAXH/1E+FPIaNFYh/NqeVG0IThWp53NozwuJAoGAa1aUQ9HokGyIcMpdLBJFL7fRQu8uNZ+FUhNHdyeU9Fg6VS7w3aiiGWQqwFa44YRI1Qe0/TWJrzi+NLcMqTRv62CsKlkssngpofBhYwnqGJsHZ4RYJq/G5H9FwKitb2L8lo5/qWk/1V9Keui22qidD2irQKSnqeNoCS6elVLrfiA=";

            //内容
            var val = "{\"tranNo\":\"XMMALL20220708175632889132\"}";

            //加密
            string encryptData = AES.Encrypt(val, Asekey);

            //解密
            string decryptData = AES.Decrypt(encryptData, Asekey);


            //登录验证

            //模拟请求参数
            ModelRequest req = new ModelRequest();

            //模拟请求参数
            var pushData = Newtonsoft.Json.JsonConvert.SerializeObject(req);

            //解析请求参数
            ModelRequest reqData = JsonConvert.DeserializeObject<ModelRequest>(pushData);

            //验签
            if (true)
            {
                SortedDictionaryPara = SetRquestData(reqData);

                if (SortedDictionaryPara.Keys.Contains("sign"))
                {
                    //验证签名
                    SortedDictionaryPara["sign"] = VerifySign(XmetaPubkey);
                }

                if (SortedDictionaryPara.Keys.Contains("objEncrypt"))
                {
                    //解密
                    var encryptBody = SortedDictionaryPara["objEncrypt"];
                    SortedDictionaryPara["objEncrypt"] = AES.Decrypt(encryptBody, Asekey);
                }
            }

            //请求返回结果

            var model =new ModelResponse();

            model.nonce = Guid.NewGuid().ToString();

            model.timestamp = Utils.GetTimeStamp();
            //1、加密
            model.objEncrypt = model.objEncrypt == null ? "" : AES.Encrypt(model.objEncrypt, Asekey);

            //2、签名
            model.sign = SetSign(model, privateKey);

            var response = Newtonsoft.Json.JsonConvert.SerializeObject(req);
        }

        /// <summary>
        ///返回参数签名
        /// </summary>
        /// <param name="baseResponse"></param>
        /// <param name="privateKey"></param>
        /// <returns></returns>
        public static string SetSign(ModelResponse baseResponse,string privateKey)
        {
            var sortedDictionary = SetResponseData(baseResponse);
            var dicArray = FilterPara(sortedDictionary, new string[] { "sign" });
            var content = CreateLinkString(dicArray);

            return Signer.SignData(content, privateKey);
        }

        /// <summary>
        /// 返回数据排序
        /// </summary>
        /// <param name="baseResponse"></param>
        /// <returns></returns>
        private static SortedDictionary<string, string> SetResponseData(ModelResponse baseResponse)
        {
            var sortedDictionaryPara = new SortedDictionary<string, string>();
            var _type = baseResponse.GetType();
            var properties = (from p in _type.GetProperties()
                              select p).ToArray<PropertyInfo>();
            foreach (var property in properties)
            {
                if (property.Name != typeof(ModelResponse).Name)
                {
                    var val = property.GetValue(baseResponse);
                    if (val != null)
                        sortedDictionaryPara.Add(property.Name, val.ToString());
                }
            }

            return sortedDictionaryPara;
        }

        /// <summary>
        /// 获取签名
        /// </summary>
        /// <returns></returns>
        private static string VerifySign(string XmetaPubkey)
        {
            try
            {
                //过滤Sign属性
                var sign = SortedDictionaryPara[CityMetaConstants.SIGN_FIELD];
                var dicArray = FilterPara(SortedDictionaryPara, new string[] { CityMetaConstants.SIGN_FIELD });
                var content = CreateLinkString(dicArray);
            
                var verify = Signer.Verify(content, sign, XmetaPubkey);
                if (!verify)
                {
                    string errorMessage = "验签失败异常，content=" + content + " sign=" + sign +
                  " publicKey=" + XmetaPubkey + " sign=" + sign;
                    throw new Exception(errorMessage);
                }

                return string.Empty;
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }



        /// <summary>
        /// 过滤数组并以字母a到z的顺序排序
        /// </summary>
        /// <param name="dicArrayPre">过滤前的参数组</param>
        /// <param name="filters">过滤条件</param>
        /// <returns>过滤后的参数组</returns>
        protected static SortedDictionary<string, string> FilterPara(SortedDictionary<string, string> dicArray, string[] filters)
        {
            var dictionary = new SortedDictionary<string, string>();
            foreach (var temp in dicArray)
            {
                if (!filters.Contains(temp.Key))
                {
                    dictionary.Add(temp.Key, temp.Value);
                }
            }

            return dictionary;
        }

        /// <summary>
        /// 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
        /// </summary>
        /// <param name="sArray">需要拼接的数组</param>
        /// <returns>拼接完成以后的字符串</returns>
        protected static string CreateLinkString(SortedDictionary<string, string> dicArray)
        {
            var sb = new StringBuilder();
            if (dicArray != null && dicArray.Count > 0)
            {
                foreach (var temp in dicArray)
                {
                    var key = temp.Key.Substring(0, 1).ToLower() + temp.Key.Substring(1);
                    sb.Append(key + "=" + temp.Value + "&");
                }
                //去掉最後一個&字符
                sb.Remove(sb.Length - 1, 1);
            }

            return sb.ToString();
        }

        /// <summary>
        /// 请求数据排序
        /// </summary>
        public static void SetRequestData(RequestModel<ModelRequest> requestModel)
        {
            var _type = requestModel.RequestParameter.GetType();

            var properties = (from p in _type.GetProperties()
                              select p).ToArray<PropertyInfo>();
            foreach (var property in properties)
            {
                if (property.PropertyType.Name != typeof(RequestModel<ModelRequest>).Name)
                {
                    var val = property.GetValue(requestModel.RequestParameter);
                    if (val != null)
                        SortedDictionaryPara.Add(property.Name, val.ToString());
                }
            }
        }

        /// <summary>
        /// 请求数据排序
        /// </summary>
        /// <param name="baseRequestModel"></param>
        /// <returns></returns>
        public static SortedDictionary<string, string> SetRquestData(ModelRequest baseRequestModel)
        {
            var sortedDictionaryPara = new SortedDictionary<string, string>();
            var _type = baseRequestModel.GetType();
            var properties = (from p in _type.GetProperties()
                              select p).ToArray<PropertyInfo>();
            foreach (var property in properties)
            {
                if (property.Name != typeof(ModelRequest).Name)
                {
                    var val = property.GetValue(baseRequestModel);
                    if (val != null)
                        sortedDictionaryPara.Add(property.Name, val.ToString());
                }
            }

            return sortedDictionaryPara;
        }

        /// <summary>
        /// md5加密
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        private string md5(string str)
        {
            //将字符串编码为字节序列
            byte[] bt = Encoding.UTF8.GetBytes(str);
            //创建默认实现的实例
            var md5 = MD5.Create();
            //计算指定字节数组的哈希值。
            var md5bt = md5.ComputeHash(bt);
            //将byte数组转换为字符串
            StringBuilder builder = new StringBuilder();
            foreach (var item in md5bt)
            {
                builder.Append(item.ToString("X2"));
            }
            string md5Str = builder.ToString();
            return builder.ToString();
        }


        /// <summary>
        /// 提交到URL的数据
        /// </summary>
        public static SortedDictionary<string, string> SortedDictionaryPara { get; internal set; }

    }

    public class CityMetaConstants
    {
        //Partner
        /// <summary>
        /// 与网关HTTP交互中涉及到的字段值
        /// </summary>
        public const string BIZ_CONTENT_FIELD = "biz_content";
        public const string SIGN_FIELD = "sign";
        public const string SIGN_TYPE_FIELD = "sign_type";
    }

}